package com.moxiao.yfjh.module.activity.controller.app;

import com.google.gson.Gson;
import com.moxiao.yfjh.framework.common.pojo.CommonResult;
import com.moxiao.yfjh.framework.common.pojo.PageResult;
import com.moxiao.yfjh.framework.excel.core.util.ExcelUtils;
import com.moxiao.yfjh.framework.operatelog.core.annotations.OperateLog;
import com.moxiao.yfjh.module.activity.common.NoCommonUtil;
import com.moxiao.yfjh.module.activity.controller.admin.activityEnroll.vo.*;
import com.moxiao.yfjh.module.activity.controller.app.vo.AppActivityInfoVo;
import com.moxiao.yfjh.module.activity.convert.activityEnroll.ActivityEnrollConvert;
import com.moxiao.yfjh.module.activity.dal.dataobject.activityEnroll.ActivityEnrollDO;
import com.moxiao.yfjh.module.activity.dal.dataobject.activityInfo.ActivityInfoDO;
import com.moxiao.yfjh.module.activity.service.activityEnroll.ActivityEnrollService;
import com.moxiao.yfjh.module.activity.service.activityInfo.ActivityInfoService;
import com.moxiao.yfjh.module.blind.dal.dataobject.member.BlindMemberUserDO;
import com.moxiao.yfjh.module.blind.service.member.BlindMemberUserService;
import com.moxiao.yfjh.module.pay.controller.admin.order.vo.PayOrderSubmitRespVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.List;
import java.util.Objects;

import static com.moxiao.yfjh.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.moxiao.yfjh.framework.common.pojo.CommonResult.success;
import static com.moxiao.yfjh.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
import static com.moxiao.yfjh.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static com.moxiao.yfjh.module.activity.enums.ErrorCodeConstants.*;

@Tag(name = "app - 相亲报名")
@RestController
@RequestMapping("/activity/enroll")
@Validated
@Slf4j
public class AppActivityEnrollController {

    @Resource
    private ActivityEnrollService enrollService;
    @Resource
    private ActivityInfoService infoService;
    @Resource
    private BlindMemberUserService memberUserService;

    @PostMapping("/create")
    @Operation(summary = "创建相亲报名信息（缴费）")
    public CommonResult<Object> createEnroll(@Valid @RequestBody ActivityEnrollCreateReqVO createReqVO) {
        BlindMemberUserDO memberUserDO = memberUserService.getMemberUser(createReqVO.getUserId());
        createReqVO.setSex(memberUserDO.getSex());
        if (StringUtils.isBlank(memberUserDO.getIdNumber())) {
            throw exception(ID_NUMBER_NOT_EXISTS);
        }
        if (Objects.nonNull(createReqVO.getActivityId())) {
            ActivityInfoDO infoDO = infoService.getInfo(createReqVO.getActivityId());
            if (Objects.nonNull(infoDO)) {
                // 验证是否已报名
                Integer enrollNum = enrollService.enrollNum(createReqVO.getActivityId(), getLoginUserId());
                if (enrollNum > 0) {
                    throw exception(ENROLL_REGISTERED_USERID_NOT_EXISTS);
                }
                // 验证活动时间是否已超期
                if (StringUtils.isNotBlank(infoDO.getDeadline())) {
                    int type = NoCommonUtil.getCompareTo(infoDO.getDeadline());
                    if (type == 1) {
                        throw exception(ENROLL_REGISTERED_USERID_NOT_EXISTS);
                    }
                }

                // 验证报名人数是否已达标
                // 男女可报名人数
                Integer num = enrollService.getEnrollNum() / 2;
                // 活动人数
                int memNum = Integer.parseInt(infoDO.getMenNum());
                int womenNum = Integer.parseInt(infoDO.getWomenNum());
                // 获取当前报名人员的性别
                Byte sex = enrollService.getMemberSex(getLoginUserId());
                // 非1v1时
                if (memNum > 1 && womenNum > 1) {
                    // 已报名人数
                    Integer mem = enrollService.getNumber(createReqVO.getActivityId(), (byte) 1, null);
                    // 已报名人数
                    Integer womem = enrollService.getNumber(createReqVO.getActivityId(), (byte) 2, null);
                    // 男生/女生 的已报名人数 大于或等于 系统设置的可报名人数时，给于提示
                    if (sex == 1) {
                        if (mem > num) {
                            throw exception(ENROLL_MAXIMUM_NUMBER_APPLICANTS_NOT_EXISTS);
                        }
                    } else {
                        if (womem > num) {
                            throw exception(ENROLL_MAXIMUM_NUMBER_APPLICANTS_NOT_EXISTS);
                        }
                    }
                } else {
                    // 已报名人数
                    Integer mem = enrollService.getNumber(createReqVO.getActivityId(), (byte) 1, null);
                    // 已报名人数
                    Integer womem = enrollService.getNumber(createReqVO.getActivityId(), (byte) 2, null);
                    // 已报名人数
                    Integer a_mem = enrollService.getNumber(createReqVO.getActivityId(), (byte) 1, (byte) 0);
                    // 已报名人数
                    Integer a_womem = enrollService.getNumber(createReqVO.getActivityId(), (byte) 2, (byte) 0);
                    // 1v1情况下，验证可报名的人数和性别，如果是已经被选中了，就不能继续报名了

                    // 判断当前用户是否是活动发起者
                    if (Objects.equals(infoDO.getHeadUserId(), getLoginUserId())) {
                        // 如果是活动发起者报名，那么 直接提示上限，不能重复报名
                        if (womem == 1 || mem == 1) {
                            throw exception(ENROLL_MAXIMUM_NUMBER_APPLICANTS_NOT_EXISTS);
                        }
                        // 发起者=男，1v1 时 10人上限 只控制报名女生的人数
                        if (sex == 2) {
                            if (womem >= 10) {
                                throw exception(ENROLL_MAXIMUM_NUMBER_APPLICANTS_NOT_EXISTS);
                            }
                        }
                    } else {
                        // 发起者=女，1v1 时 10人上限 只控制报名的男生的人数
                        if (sex == 1) {
                            if (a_mem == 1) {
                                throw exception(ENROLL_MAXIMUM_NUMBER_APPLICANTS_NOT_EXISTS);
                            }
                            if (mem >= 10) {
                                throw exception(ENROLL_MAXIMUM_NUMBER_APPLICANTS_NOT_EXISTS);
                            }
                        } else {
                            if (a_womem == 1) {
                                throw exception(ENROLL_MAXIMUM_NUMBER_APPLICANTS_NOT_EXISTS);
                            }
                        }
                    }
                }

                if (Objects.equals(createReqVO.getUserId(), infoDO.getHeadUserId())) {
                    // 活动：发起者默认是参与者
                    createReqVO.setActivityStatus((byte) 0);
                    // 活动：发起者缴费/且活动是带缴费状态的，变更活动状态为可报名
                    if (infoDO.getStatus() == 1) {
                        if (Objects.equals(createReqVO.getUserId(), infoDO.getHeadUserId())) {
                            infoService.updateByStatus(infoDO.getId(), (byte) 2);
                        }
                    }
                    // 活动：发起者缴费 活动的缴费金额：根据分佣分摊类型 2= 发起人全款
                    if (infoDO.getCostShare() == 2) {
                        int r_num = Integer.parseInt(infoDO.getMenNum()) + Integer.parseInt(infoDO.getWomenNum());
                        BigDecimal intToBigDecimal = new BigDecimal(r_num);
                        // 使用 BigDecimal 的乘法方法进行计算
                        BigDecimal result = intToBigDecimal.multiply(infoDO.getActiveCost());
                        createReqVO.setPayAmount(result);
                    }
                } else {
                    // 个人活动的报名是直接非选中，官方活动的报名是直接选中
                    if (infoDO.getActiveSource().equals("1")) {
                        createReqVO.setActivityStatus((byte) 0);
                    } else {
                        createReqVO.setActivityStatus((byte) 1);
                        // 费发起人，但是是发起人全款，则其他人报名是0.00元
                        if (infoDO.getCostShare() == 2) {
                            createReqVO.setPayAmount(BigDecimal.valueOf(0.00));
                        }
                    }
                }
            }
            String no = "EN_" + NoCommonUtil.dateTime() + "_" + NoCommonUtil.getRandom();
            createReqVO.setNo(no);

            if (createReqVO.getDeviceType() == 1) {
                // 待缴费
                createReqVO.setStatus((byte) -1);
            } else {
                // 已报名
                createReqVO.setStatus((byte) 0);
            }
            // 创建活动报名支付订单
            PayOrderSubmitRespVO respVO = new PayOrderSubmitRespVO();
            if (createReqVO.getPayAmount().compareTo(BigDecimal.ZERO) > 0) {
                ActivityEnrollDO enroll = enrollService.createAppEnroll(createReqVO);
                // 区分走支付和不走支付
                if (createReqVO.getDeviceType() == 1) {
                    respVO = enrollService.createPayOrder(enroll.getId());
                    Gson gson = new Gson();
                    Object jsonObject;
                    if (createReqVO.getPayType() == 1) {
                        jsonObject = gson.fromJson(respVO.getDisplayContent(), Object.class);
                    } else {
                        jsonObject = respVO.getDisplayContent();
                    }
                    log.error("报名支付返回respVO-【{}】】", respVO.getDisplayContent());
                    return success(jsonObject);
                } else {
                    return success(Boolean.TRUE);
                }
            } else {
                // 全款制不用缴费直接报名
                createReqVO.setStatus((byte) 0);
                enrollService.createAppEnroll(createReqVO);
                return success(new Object());
            }
        } else {
            throw exception(ENROLL_NO_RELATED_ACTIVITIES_FOUND_NOT_EXISTS);
        }
    }

    @PostMapping("/customCreate")
    @Operation(summary = "创建相亲报名信息（缴费）")
    public CommonResult<Object> customCreate(@Valid @RequestBody ActivityEnrollCreateReqVO createReqVO) {
        BlindMemberUserDO memberUserDO = memberUserService.getMemberUser(createReqVO.getUserId());
        createReqVO.setSex(memberUserDO.getSex());
        //0. 验证是否已登录
        if (StringUtils.isBlank(memberUserDO.getIdNumber())) {
            throw exception(ID_NUMBER_NOT_EXISTS);
        }
        if (Objects.nonNull(createReqVO.getActivityId())) {
            ActivityInfoDO infoDO = infoService.getInfo(createReqVO.getActivityId());
            if (Objects.nonNull(infoDO)) {
                //1. 验证是否已报名
                Integer enrollNum = enrollService.enrollNum(createReqVO.getActivityId(), getLoginUserId());
                if (enrollNum > 0) {
                    throw exception(ENROLL_REGISTERED_USERID_NOT_EXISTS);
                }
                //2. 验证活动时间是否已超期
                if (StringUtils.isNotBlank(infoDO.getDeadline())) {
                    int type = NoCommonUtil.getCompareTo(infoDO.getDeadline());
                    if (type == 1) {
                        throw exception(ENROLL_REGISTERED_USERID_NOT_EXISTS);
                    }
                }
                if (!infoDO.getMenNum().equals("-1")) {
                    //2.1 验证报名人数是否已达标,男女可报名人数
                    Integer num = enrollService.getEnrollNum() / 2;
                    // 活动人数
                    Integer memNum = Integer.valueOf(infoDO.getMenNum());
                    Integer womenNum = Integer.valueOf(infoDO.getWomenNum());
                    // 获取当前报名人员的性别
                    Byte sex = enrollService.getMemberSex(getLoginUserId());
                    // 非1v1时
                    if (memNum > 1 && womenNum > 1) {
                        // 已报名人数
                        Integer mem = enrollService.getNumber(createReqVO.getActivityId(), (byte) 1, null);
                        // 已报名人数
                        Integer womem = enrollService.getNumber(createReqVO.getActivityId(), (byte) 2, null);
                        // 男生/女生 的已报名人数 大于或等于 系统设置的可报名人数时，给于提示
                        if (sex == 1) {
                            if (mem > num) {
                                throw exception(ENROLL_MAXIMUM_NUMBER_APPLICANTS_NOT_EXISTS);
                            }
                        } else {
                            if (womem > num) {
                                throw exception(ENROLL_MAXIMUM_NUMBER_APPLICANTS_NOT_EXISTS);
                            }
                        }
                    } else {
                        // 已报名人数
                        Integer mem = enrollService.getNumber(createReqVO.getActivityId(), (byte) 1, null);
                        // 已报名人数
                        Integer womem = enrollService.getNumber(createReqVO.getActivityId(), (byte) 2, null);
                        // 已报名人数
                        Integer a_mem = enrollService.getNumber(createReqVO.getActivityId(), (byte) 1, (byte) 0);
                        // 已报名人数
                        Integer a_womem = enrollService.getNumber(createReqVO.getActivityId(), (byte) 2, (byte) 0);
                        // 1v1情况下，验证可报名的人数和性别，如果是已经被选中了，就不能继续报名了

                        // 判断当前用户是否是活动发起者
                        if (Objects.equals(infoDO.getHeadUserId(), getLoginUserId())) {
                            // 如果是活动发起者报名，那么 直接提示上限，不能重复报名
                            if (womem == 1 || mem == 1) {
                                throw exception(ENROLL_MAXIMUM_NUMBER_APPLICANTS_NOT_EXISTS);
                            }
                            // 发起者=男，1v1 时 10人上限 只控制报名女生的人数
                            if (sex == 2) {
                                if (womem >= 10) {
                                    throw exception(ENROLL_MAXIMUM_NUMBER_APPLICANTS_NOT_EXISTS);
                                }
                            }
                        } else {
                            // 发起者=女，1v1 时 10人上限 只控制报名的男生的人数
                            if (sex == 1) {
                                if (a_mem == 1) {
                                    throw exception(ENROLL_MAXIMUM_NUMBER_APPLICANTS_NOT_EXISTS);
                                }
                                if (mem >= 10) {
                                    throw exception(ENROLL_MAXIMUM_NUMBER_APPLICANTS_NOT_EXISTS);
                                }
                            } else {
                                if (a_womem == 1) {
                                    throw exception(ENROLL_MAXIMUM_NUMBER_APPLICANTS_NOT_EXISTS);
                                }
                            }
                        }
                    }
                }
                //直接报名
                String no = "EN_" + NoCommonUtil.dateTime() + "_" + NoCommonUtil.getRandom();
                createReqVO.setNo(no);
                createReqVO.setStatus((byte) 0);
                createReqVO.setUserId(getLoginUserId());
                createReqVO.setSex(memberUserDO.getSex());
                createReqVO.setActivityStatus((byte) 0);
                createReqVO.setPayAmount(new BigDecimal("0.00"));
                createReqVO.setIsPair((byte) 1);
                enrollService.createAppEnroll(createReqVO);
            }
        }
        return success(Boolean.TRUE);
    }



    @PutMapping("/update")
    @Operation(summary = "更新相亲报名信息")
    public CommonResult<Boolean> updateEnroll(@Valid @RequestBody ActivityEnrollUpdateReqVO updateReqVO) {
        updateReqVO.setActivityStatus((byte) 0);
        enrollService.updateEnroll(updateReqVO);
        return success(true);
    }


    @GetMapping("/get")
    @Operation(summary = "获得相亲报名信息")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    public CommonResult<ActivityEnrollRespVO> getEnroll(@RequestParam("id") Long id) {
        ActivityEnrollDO enroll = enrollService.getEnroll(id);
        return success(ActivityEnrollConvert.INSTANCE.convert(enroll));
    }


    @GetMapping("/list")
    @Operation(summary = "获得相亲报名信息列表")
    @Parameter(name = "ids", description = "编号列表", required = true, example = "1024,2048")
    public CommonResult<List<ActivityEnrollRespVO>> getEnrollList(@RequestParam("ids") Collection<Long> ids) {
        List<ActivityEnrollDO> list = enrollService.getEnrollList(ids);
        return success(ActivityEnrollConvert.INSTANCE.convertList(list));
    }

    @GetMapping("/page")
    @Operation(summary = "获得相亲报名信息分页")
    public CommonResult<PageResult<ActivityEnrollRespVO>> getEnrollPage(@Valid ActivityEnrollPageReqVO pageVO) {
        PageResult<ActivityEnrollDO> pageResult = enrollService.getEnrollPage(pageVO);
        PageResult<ActivityEnrollRespVO> pageList = ActivityEnrollConvert.INSTANCE.convertPage(pageResult);
        return success(pageList);
    }

    @GetMapping("/export-excel")
    @Operation(summary = "导出相亲报名信息 Excel")
    @OperateLog(type = EXPORT)
    public void exportEnrollExcel(@Valid ActivityEnrollExportReqVO exportReqVO,
                                  HttpServletResponse response) throws IOException {
        List<ActivityEnrollDO> list = enrollService.getEnrollList(exportReqVO);
        // 导出 Excel
        List<ActivityEnrollExcelVO> datas = ActivityEnrollConvert.INSTANCE.convertList02(list);
        ExcelUtils.write(response, "相亲报名信息.xls", "数据", ActivityEnrollExcelVO.class, datas);
    }

    @GetMapping("/getAppActivityEnrollList")
    @Parameter(name = "activityId", description = "活动id", required = true, example = "1")
    @Operation(summary = "获得相亲报名信息")
    public CommonResult<AppActivityInfoVo> getEnrollPage(@RequestParam("activityId") Long activityId) {
        AppActivityInfoVo vo = enrollService.getEnrollPage(activityId, getLoginUserId());
        if (Objects.nonNull(vo)) {
            ActivityInfoDO infoDO = infoService.getInfo(activityId);
            if (Objects.nonNull(infoDO)) {
                // 男女可报名人数
//                Integer num = enrollService.getEnrollNum() / 2;
                // 活动人数
                Integer memNum = Integer.valueOf(infoDO.getMenNum());
                Integer womenNum = Integer.valueOf(infoDO.getWomenNum());
                // 男生已组队人数
                Integer mem = enrollService.getNumber(activityId, (byte) 1, (byte) 0);
                // 女生已组队人数
                Integer womem = enrollService.getNumber(activityId, (byte) 2, (byte) 0);
                // 非1v1时
                vo.setEnrollMenNumber(memNum - mem);
                vo.setEnrollWomenNumber(womenNum - womem);
            }
        }
        return success(vo);
    }
}
